﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;

namespace Mindfor.Web
{
	/// <summary>
	/// Represents view engine that renders page using Razor syntax and accepts module parameter.
	/// </summary>
	public class CmsRazorViewEngine : RazorViewEngine
	{
		/// <summary>
		/// Initializes new instance.
		/// </summary>
		public CmsRazorViewEngine()
		{
			string[] viewLocationFormats = new string[] {
				"~/Modules/[module]/Views/{1}/{0}.cshtml",
				"~/Modules/[module]/Views/{1}/{0}.vbhtml",
				"~/Modules/[module]/Views/Shared/{0}.cshtml",
				"~/Modules/[module]/Views/Shared/{0}.vbhtml",
				"~/Modules/Shared/{0}.cshtml",
				"~/Modules/Shared/{0}.vbhtml",
				"~/Views/{1}/{0}.cshtml",
                "~/Views/{1}/{0}.vbhtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Views/Shared/{0}.vbhtml"
			};

			ViewLocationFormats = viewLocationFormats;
			MasterLocationFormats = viewLocationFormats;
			PartialViewLocationFormats = viewLocationFormats;
		}

		protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
		{
			viewPath = ReplaceModule(controllerContext, viewPath);
			masterPath = ReplaceModule(controllerContext, masterPath);
			return base.CreateView(controllerContext, viewPath, masterPath);
		}

		protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
		{
			partialPath = ReplaceModule(controllerContext, partialPath);
			return base.CreatePartialView(controllerContext, partialPath);
		}

		protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
		{
			virtualPath = ReplaceModule(controllerContext, virtualPath);
			return base.FileExists(controllerContext, virtualPath);
		}

		/// <summary>
		/// Replaces [module] in virtual path with module name from route.
		/// If  path does not contains [module] then returns "as is".
		/// If path contains [module] and route does not contains module name then returns null.
		/// </summary>
		/// <param name="controllerContext">Controller context.</param>
		/// <param name="virtualPath">Virtual path.</param>
		private string ReplaceModule(ControllerContext controllerContext, string virtualPath)
		{
			if (virtualPath.Contains("[module]"))
			{
				object moduleObj;
				if (controllerContext.RouteData.Values.TryGetValue("module", out moduleObj))
					virtualPath = virtualPath.Replace("[module]", moduleObj.ToString());
				else
					return null;
			}
			return virtualPath;
		}
	}
}
